package chaussitag.storagespy;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.os.FileObserver;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.StatFs;
import android.os.storage.StorageManager;
import android.util.Log;

public class SdcardObserverService extends Service {

	private static final String TAG = "SdcardObserverService";

	private int mNotificationId = R.drawable.app_icon;

	private int mInterestedChanges =
		FileObserver.CREATE | FileObserver.DELETE_SELF | FileObserver.MOVED_FROM | FileObserver.MOVED_TO;

	private Handler mHandler;
	private boolean mServicing = false;
	private RecursiveFileObserver mSdcardObserver =
		new RecursiveFileObserver(mInterestedChanges);

	private LocalBinder mBinder = new LocalBinder(false);
	
	@Override
	public void onCreate() {
		Log.d(TAG, "onCreate");
		HandlerThread thread =
			new HandlerThread("SdcardObserverServiceThread", android.os.Process.THREAD_PRIORITY_BACKGROUND);
		thread.start();
		mHandler = new Handler(thread.getLooper());
	}

	@Override
	public int onStartCommand(final Intent intent, int flags, int startId) {
		Log.d(TAG, "onStartCommand");
		if (mServicing)
			return START_STICKY;

		mBinder.setObserving(true);

		mServicing = true;

		mHandler.post(new Runnable() {
			@Override
			public void run() {
				startObserveSdcard();
				setForground();
				PendingIntent broadcast = intent.getExtras().getParcelable("broadcast");
				if (broadcast != null) {
					try {
						broadcast.send();
					} catch (CanceledException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		});

		return START_STICKY;
	}

	@Override
	public void onDestroy() {
		stopObserveSdcard();
	}

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}

	private void setForground() {
		Intent intentToStartMainActivity = new Intent(this, MainActivity.class);
		PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intentToStartMainActivity, 0);
		Notification notification =
				new Notification(R.drawable.app_icon,
					getResources().getText(R.string.observing_notification_ticker_text),
					System.currentTimeMillis());
		notification.setLatestEventInfo(this,
			getResources().getText(R.string.observeing_notification_title),
			getResources().getText(R.string.observing_notification_content), pendingIntent);
		startForeground(mNotificationId, notification);
	}

	private void startObserveSdcard() {
		mSdcardObserver.setFileEventListener(mFileEventListener);
		mSdcardObserver.startWatching(getStoragePaths(this));
	}

	private void stopObserveSdcard() {
		mSdcardObserver.stopWatching();
		try {
			if (mBuffWriter != null) {
				mBuffWriter.close();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static String[] sStoragePaths;

	@SuppressLint("NewApi")
	private static String[] getStoragePaths(Context context) {
		if (sStoragePaths == null) {
			sStoragePaths = new String[0];
			StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
			try {
	    	    Class<?>[] paramClasses = {};
	    	    Method getVolumePathsMethod = sm.getClass().getMethod("getVolumePaths", paramClasses);
	    	    getVolumePathsMethod.setAccessible(true);
	    	    Object[] params = {};
	    	    Object invoke = getVolumePathsMethod.invoke(sm, params);
	    	    String[] paths = (String[])invoke;
	    	
	    	    ArrayList<String> localList = new ArrayList<String>();
	    	    for (int i = 0; i < paths.length; i++) {
	    	    	if (paths[i].toLowerCase(Locale.ROOT).indexOf("usb") != -1) {
	    		    	continue;
	    		    }
	    		    
	                long totalSize = getTotalSdcardMemorySize(paths[i]);
	                if (totalSize > 0) {
	                	localList.add(paths[i]);
	                }
	    	    }
	
	    	    sStoragePaths = localList.toArray(sStoragePaths);
	        } catch (Exception e1) {
	        	File file = Environment.getExternalStorageDirectory();
	        	String path = file.getAbsolutePath();
	        	sStoragePaths = new String[] {path};
		    }
			Log.d(TAG, "storage paths: ");
			for (String str : sStoragePaths) {
				Log.d(TAG, "    " + str);
			}
		}

		return sStoragePaths;
	}

    public static long getTotalSdcardMemorySize(String path) {
    	try {
            StatFs stat = new StatFs(path);
            long blockSize = stat.getBlockSize();
            long totalBlocks = stat.getBlockCount();
            return totalBlocks * blockSize;
    	} catch (Exception e) {
    		Log.i(TAG, "getTotalSdcardMemorySize error, " + e.getMessage());
    	}
    	return 0;
    }
	
	private RecursiveFileObserver.FileEventListener mFileEventListener =
		new RecursiveFileObserver.FileEventListener() {
		    // 这里收到的通知，已经全部是目录的变化了(RecursiveFileObserver已经判断过)，不需要再判断一次
			@Override
			public void onEvent(int event, String path, Date time) {
				String action = null;
				switch (event) {
				case FileObserver.CREATE:
					action = "Created";
					break;
				case FileObserver.DELETE_SELF:
					action = "Deleted";
					break;
				case FileObserver.MOVED_FROM:
					action = "MovedFr";
					break;
				case FileObserver.MOVED_TO:
					action = "MovedTo";
					break;
				default:
					break;
				}

				if (action != null) {
					SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
					StringBuilder builder = new StringBuilder(format.format(time));
					// 用tab作为字段分隔符，便于将生成的文本文件直接导入到excel里面
					builder.append("\t").append(action).append("\t").append(path);
					writeToFile(builder.toString());
				}
			}
	};

	private final String mRecordPath = "/sdcard/storageobserve.txt";
	private BufferedWriter mBuffWriter;
	private void writeToFile(String record) {
		Log.d(TAG, record);
		if (mBuffWriter == null) {
			try {
				File file = new File(mRecordPath);
				if (!file.exists()) {
					file.createNewFile();
				}
				mBuffWriter = new BufferedWriter(new FileWriter(mRecordPath));
			} catch (IOException e) {
				mBuffWriter = null;
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		if (mBuffWriter != null) {
			try {
				mBuffWriter.write(record);
				mBuffWriter.newLine();
			} catch (IOException e) {
				Log.e(TAG, "failed to write record: " + record);
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
